package com.yoso.base.service;


import cn.hutool.core.collection.CollUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.yoso.base.entity.BaseEntity;
import com.yoso.base.infrastructure.dao.BaseMapper;
import com.yoso.base.infrastructure.page.SearchParam;
import com.yoso.base.infrastructure.utils.IdUtil;
import com.yoso.base.interfaces.vo.BaseVo;
import com.yoso.base.interfaces.vo.PageVo;
import com.yoso.base.pojo.PagePojo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ObjectUtils;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author shizejin
 * @date 2021/11/9
 */
public abstract class BaseService<E extends BaseEntity, V extends BaseVo, M extends BaseEntityExample> extends AbstractBaseService<E, V, M> {

    @Autowired(required = false)
    private BaseMapper<E, M> baseMapper;

    public abstract M getEntityExample(Map<String, String> paramMap);

    @Override
    public long countByExample(M example) {
        return this.baseMapper.countByExample(example);
    }

    @Override
    public int deleteByExample(M example) {
        return this.baseMapper.deleteByExample(example);
    }

    @Override
    public int deleteByPrimaryKey(String id) {
        return this.baseMapper.deleteByPrimaryKey(id);
    }

    @Override
    public int insert(V record) {
        if (StringUtils.isBlank(record.getId())) {
            record.setId(IdUtil.buildId());
            return this.baseMapper.insert(V2E(record));
        }
        return this.baseMapper.updateByPrimaryKey(V2E(record));
    }

    @Override
    public int insertSelective(V record) {
        if (StringUtils.isBlank(record.getId())) {
            record.setId(IdUtil.buildId());
            return this.baseMapper.insertSelective(V2E(record));
        }
        return this.baseMapper.updateByPrimaryKeySelective(V2E(record));
    }

    @Override
    public List<V> selectByExample(M example) {
        return bachE2V(this.baseMapper.selectByExample(example));
    }

    @Override
    public V selectByPrimaryKey(String id) {
        return E2V(this.baseMapper.selectByPrimaryKey(id));
    }

    @Override
    public int updateByExampleSelective(V record, M example) {
        return this.baseMapper.updateByExampleSelective(V2E(record), example);
    }

    @Override
    public int updateByExample(V record, M example) {
        return this.baseMapper.updateByExample(V2E(record), example);
    }

    @Override
    public int updateByPrimaryKeySelective(V record) {
        return this.baseMapper.updateByPrimaryKeySelective(V2E(record));
    }

    @Override
    public int updateByPrimaryKey(V record) {
        return this.baseMapper.updateByPrimaryKey(V2E(record));
    }

    @Override
    public PageInfo<V> pageConditionsList(PageVo pageVo) {
        if (ObjectUtils.isEmpty(pageVo) || ObjectUtils.isEmpty(pageVo.getPagePojo())) {
            return new PageInfo<>(bachE2V(this.baseMapper.selectByExample(null)));
        }
        PagePojo pagePojo = pageVo.getPagePojo();
        List<SearchParam> searchParamList = pageVo.getSearchParamList();
        Map<String, String> paramMap = CollUtil.newHashMap();
        if (CollUtil.isNotEmpty(searchParamList)) {
            paramMap = handlerParam(searchParamList);
        }
        M entityExample = this.getEntityExample(paramMap);
        if (!ObjectUtils.isEmpty(pagePojo)) {
            PageHelper.startPage(pagePojo.getCurPage(), pagePojo.getPageSize());
        }
        /**
         * 使用PageHelper分页，不可以将数据库中查出来的list转为其他list，可以直接封装DTO在数据库中直接返回你需要的数据类型，不要查询出来之后再去转换,这样会导致PageHelper中pageInfo失效。
         */
        List<E> list2 = baseMapper.selectByExample(entityExample);
        PageInfo<E> ePageInfo = new PageInfo<>(list2);
        List<V> vos = this.bachE2V(ePageInfo.getList());
        PageInfo<V> vPageInfo = new PageInfo<>();
        BeanUtils.copyProperties(ePageInfo, vPageInfo, "list");
        vPageInfo.setList(vos);
        return vPageInfo;
    }

    public Map<String, String> handlerParam(List<SearchParam> searchParamList) {
        return searchParamList.parallelStream()
                .collect(Collectors.toMap(SearchParam::getKey, SearchParam::getValue, (o1, o2) -> o1));
    }

    @Override
    public List<V> listAll() {
        return bachE2V(this.baseMapper.selectByExample(null));
    }

    @Override
    public int saveRecord(V record) {
        if (ObjectUtils.isEmpty(record)) {
            return 0;
        }
        record.setId(null);
        return this.insert(record);
    }

    @Override
    public int updateRecord(V record) {
        if (ObjectUtils.isEmpty(record)) {
            return 0;
        }
        return this.updateByPrimaryKey(record);
    }
}
